﻿using gt.webapi.core.Entity.Common;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Text;

namespace gt.webapi.core.Extensions
{
    public static class HttpRequestMessageExtension
    {
        private const string HTTPCONTEXT = "MS_HttpContext";
        private const string REMOTE_ENDPOINT_MESSAGE = "System.ServiceModel.Channels.RemoteEndpointMessageProperty";
        private const string REMOTE_PORT = "REMOTE_PORT";
        private const string OWINCONTEXT = "MS_OwinContext";
        private const string X_REAL_IP = "x-real-ip";

        public static string GetUrlParam(this HttpRequestMessage httpRequestMessage)
        {
            if (httpRequestMessage == null) return string.Empty;
            var args = httpRequestMessage.GetQueryNameValuePairs();
            StringBuilder s = new StringBuilder();

            if (args != null && args.Count() != 0)
            {
                foreach (var arg in args)
                {
                    s.Append(arg.Key).Append("=").Append(arg.Value).Append(",");
                }
            }
            return s.ToString().TrimEnd(',');
        }
        public static string GetRequestString(this HttpRequestMessage httpRequestMessage)
        {
            if (httpRequestMessage == null) return string.Empty;
            return httpRequestMessage.Content.ReadAsStringAsync().Result;
        }
        public static string GetRequestId(this HttpRequestMessage httpRequestMessage)
        {
            string requestId = string.Empty;
            if (httpRequestMessage.Properties.ContainsKey(Constants.API_PROPERTY_REQUESTID))
                requestId = httpRequestMessage.Properties[Constants.API_PROPERTY_REQUESTID].ToString();
            return requestId;
        }
        public static string GetControllerActionPath(this HttpRequestMessage httpRequestMessage)
        {
            var actionDescriptor = httpRequestMessage.GetActionDescriptor();
            if (actionDescriptor == null) return string.Empty;
            return string.Format("{0}/{1}", actionDescriptor.ControllerDescriptor.ControllerName, actionDescriptor.ActionName);
        }
        public static string GetAppKey(this HttpRequestMessage httpRequestMessage)
        {
            if(httpRequestMessage.GetRequestContext().Principal!=null)
                return httpRequestMessage.GetRequestContext().Principal.Identity.Name;
            return string.Empty;
        }
        public static double GetDurationTime(this HttpRequestMessage httpRequestMessage)
        {
            Stopwatch watch = null;
            if (httpRequestMessage.Properties.ContainsKey(Constants.API_PROPERTY_STOPWATCH))
                watch = httpRequestMessage.Properties[Constants.API_PROPERTY_STOPWATCH] as Stopwatch;
            if (watch != null && watch.IsRunning)
            {
                watch.Stop();
                return watch.ElapsedMilliseconds;
            }
            return 0.0;
        }
        public static string GetClientRealIp(this HttpRequestMessage httpRequestMessage)
        {
            string realIp = "0.0.0.0";
            if (httpRequestMessage.Properties.ContainsKey(HTTPCONTEXT))
            {
                dynamic ctx = httpRequestMessage.Properties[HTTPCONTEXT];
                if (ctx != null)
                    return ctx.Request.UserHostAddress;
            }
            if (httpRequestMessage.Properties.ContainsKey(REMOTE_ENDPOINT_MESSAGE))
            {
                dynamic remoteEndpoint = httpRequestMessage.Properties[REMOTE_ENDPOINT_MESSAGE];
                if (remoteEndpoint != null)
                    return remoteEndpoint.Address;
            }
            if (httpRequestMessage.Properties.ContainsKey("MS_OwinContext"))
            {
                dynamic owinContext = httpRequestMessage.Properties[OWINCONTEXT];//Microsoft.Owin.OwinContext
                if (owinContext != null)
                {
                    realIp = owinContext.Request.Headers[X_REAL_IP];
                    if (string.IsNullOrEmpty(realIp))
                        return owinContext.Request.RemoteIpAddress;
                }
            }
            return realIp;
        }
    }
}
